package ij.umasuo.AOTFController;

import ij.IJ;
import ij.ImagePlus;
import ij.umasuo.MyConstants;
import ij.umasuo.MyUserSettings;
import ij.umasuo.algorithms.AlgorithmManager;
import ij.umasuo.gui.laserCtr.dstorm.DStormEditor;
import ij.umasuo.gui.working.LiveViewer;
import ij.umasuo.gui.working.WorkingViewer;

import java.util.ArrayList;
import java.util.List;

public class DStormCtr implements CtrInterface{

	private AOTFClient aotfClient = AOTFClient.getInstance();
	private static DStormCtr instance = null;
	private static boolean isTakingData = false;//to show if we are acquiring images
	private static boolean isLasersOn = false;// this use to show whether we have turn on the laser
	private static int curCount = 0;
	private static int maxCount = Integer.MAX_VALUE;
	private static List<String> images = new ArrayList<String>();//the images we got
	private static int imageIndex = 0;//current index of images
	private DStormEditor dsViewer = null;
	private CameraThread cameraThread = null;
	private DStormCtr() {}
	
	public void setViwer(DStormEditor ds){
		this.dsViewer = ds;
	} 

	/**
	 * refresh the laser ,be called in laser
	 */
	public void refreshLaser() {
		if (!isLasersOn) {
			return;// only when the lasers have been turn on, we need to refresh  the laser
		}
		// here we write the commands to the aotfController
		for (int i = 0; i < MyUserSettings.dstLasers.size(); i++) {
			aotfClient.Write("dds a " + MyConstants.laserID.get(MyUserSettings.dstLasers.get(i)) + " " + MyUserSettings.dstLaserInt.get(i) + "\r");
		}
	}

	/**
	 * power on the lasers
	 */
	public void powerOnLasers(){
		isLasersOn = true;
		aotfClient.resetAOTF();
		// here we write the commands to the aotfController
		for (int i = 0; i < MyUserSettings.dstLasers.size(); i++) {
			aotfClient.Write("dds a " + MyConstants.laserID.get(MyUserSettings.dstLasers.get(i)) + " " + MyUserSettings.dstLaserInt.get(i) + "\r");
		}
	}
	
	/**
	 * power off the lasers
	 */
	public void powerOffLasers(){
		isLasersOn = false;
		aotfClient.resetAOTF();
	}

	/**
	 * get the instance
	 * @return
	 */
	public static DStormCtr getInstance() {
		if (instance == null) {
			instance = new DStormCtr();
		}
		return instance;
	}

	

	/**
	 * start to acquire data from the camera
	 * @param maxCount the maxCount images we will get
	 */
	public void startGettingData(int maxCount){
//		if(camera == null){ //we will use this later
//			camera = Camera.getInstance();
//		}
		MyConstants.setFileSavePath();
		if(instance == null){
			instance = getInstance();
		}
		isTakingData = true;
		if(maxCount <=0){
			DStormCtr.maxCount = Integer.MAX_VALUE;
		}else{
			DStormCtr.maxCount = maxCount;
		}
		curCount = 0;
		images.clear();
		imageIndex = 0;
//		DStormCtr tmp = new DStormCtr();
//		tmp.setViwer(dsViewer);
//		instance = tmp;

		//here we start the process
		AlgorithmManager.getInstance().setSourceModel(MyConstants.ALGORITHM_ONLINE);
		AlgorithmManager.getInstance().setOnlineImgSrouce(DStormCtr.getInstance());
//		AlgorithmManager.getInstance().startProcessStorm();
		AlgorithmManager.getInstance().startProcess();
		cameraThread = new CameraThread();
		cameraThread.start();
	}
	
	/**
	 * stop getting data
	 */
	public void stopTakingData(){
		isTakingData = false;
		MyConstants.isCanTakingDate = false;
//		if(cameraThread != null){
//			try {
//				cameraThread.join();
//			} catch (InterruptedException e) {
//				IJ.log(e.toString());
//			}
//		}
//		IJ.log("thread stoped!!");
		AlgorithmManager.getInstance().stopProcess();
	}
	
	/**
	 * 
	 * @return
	 */
	public static boolean isTakingData(){
		return isTakingData;
	}

	@Override
	public ImagePlus getNextImage() {
		ImagePlus tmpImp = null;
		synchronized(images){
			if(imageIndex >= images.size()){
				return null;//no more
			}
			tmpImp = new ImagePlus(images.get(imageIndex));//here we may change the way we save the images
			imageIndex++;
		}
		return tmpImp;
	}
	

	@Override
	public String getNextImagePath() {
		String path = null;
		synchronized(images){
			if(imageIndex >= images.size()){
				return null;//no more
			}
			path = images.get(imageIndex);//here we may change the way we save the images
			imageIndex++;
		}
		return path;
	}

	@Override
	public String getNextImagePath(int channel) {
		return null;
	}

	@Override
	public ImagePlus getNextImage(int channel) {
		return null;
	}

	@Override
	public int getNextChannel() {
		return 0;
	}

	@Override
	public int getTotalImageCount() {
		if(images!=null){
			return images.size();
		}
		return 0;
	}
	
	/**
	 * add one image into the image list and refresh the working window
	 */
	public void addImage(String image){
		synchronized(images){
			if(image != null){
				images.add(image);
				curCount ++;
				ImagePlus imp = new ImagePlus(image);
				WorkingViewer.getInstance().updataWorkingCanvas(0, imp.getImage());
				if(curCount >= DStormCtr.maxCount){
	//				isTakingData = false;
					IJ.showMessage("Takeing data finished!");
					DStormEditor.getInstance().finishTakeData();
				}
			}
		}
	}
	
	public int getCurCount(){
		return curCount;
	}
	
	
	public class CameraThread extends Thread{
		/**
		 * start to get image
		 */
		@Override
		public void run() {
			IJ.runPlugIn("CameraPlugin", "dstorm:"+maxCount);
		}
	}


	/**
	 * get the current image's index
	 */
	@Override
	public int getNextFrame() {
		return imageIndex;
	}
}

